from database import Database
import re
import socket
import struct

class HostGroup:
	def __init__(self, hostgroup_id):
		self.db = Database()
		self.id = hostgroup_id
		self._ip_regexp = re.compile("^(?P<ip>((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d))(?P<port>:[0-65535])$")
		self._url_regexp = re.compile("^((https?|ftp):\/\/)?(?P<host>[^\/]+)(\/.*)?$")

		if self.id != -1:
			# Get host group type
			sql = "SELECT type FROM host_group WHERE idhost_group = '" + str(self.id) + "'"	
			res = self.db.execute(sql)
			self.type = res[0]['type']

			# Get host group members
			sql = "SELECT * FROM host_group_members " + \
				"INNER JOIN properties ON host_group_members.idc_property = properties.idproperty " + \
				"WHERE host_group_members.idc_host_group = '" + str(self.id) + "' " + \
				"ORDER BY host_group_members.group_order"
			res = self.db.execute(sql)
			self.members = []
			for member in res:
				m = ( member['property'], member['value'] )
				self.members.append(m)

	def match(self, host):
		if self.id == -1:
			return True
		if self.type == 'ip':
			return self._match_ip(host)
		else:
			return self._match_url(host)

	def _match_ip(self, ip):
		ip = self._get_ip(ip)
		for prop in self.members:
			if prop[0] == "IN_NET":
				if not self.addressInNetwork(ip, prop[1]):
					return False

			if prop[0] == "NOT_IN_NET":
				if self.addressInNetwork(ip, prop[1]):
					return False
		return True

	def _match_url(self, url):
		for prop in self.members:
			if prop[0] == "MATCH_REGEX":
				try:
					res = re.search(prop[1], url)
					if not res:
						return False
				except:
					return False
		return True

	def _get_ip(self, path):
		res = self._ip_regexp.match(path)
		if res:
			return res.group('ip')
		else:
			res = self._url_regexp.match(path)
			if res:
				try:
					return socket.gethostbyname(res.group('host'))
				except:
					pass

			return False

	def addressInNetwork(self, ip, net):
		try:
			ipaddr = struct.unpack('L',socket.inet_aton(ip))[0]
			netaddr,bits = net.split('/')
			netmask = struct.unpack('L',socket.inet_aton(netaddr))[0] & ((2L<<int(bits)-1) - 1)
			return ipaddr & netmask == netmask
		except:
			return False
